home *** CD-ROM | disk | FTP | other *** search
Wrap
/* File: intrface.c Copyright (C) 1998-2004 Christophe GRENIER <grenier@cgsecurity.org> This software is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include <stdarg.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <ctype.h> #include <unistd.h> /* geteuid */ #include "types.h" #include "common.h" #include "lang.h" #include "intrface.h" #include "readpart.h" #include "godmode.h" #include "fnctdsk.h" #include "testdisk.h" #include "fat.h" #include "ext2_dir.h" #include "rfs.h" #include "ntfs.h" #include "adv.h" extern char* nom_os[256]; static void interface_options(int *paranoid,int *dump_ind,int *fast_mode,int *align,int *recover_cih,int *allow_partial_last_cylinder,int *ask_part_order,int *halt_on_errors, int *max_ext); #define GS_DEFAULT -1 #define GS_key_ESCAPE -2 static void aff_CHS_from_LBA(WINDOW *window, const t_param_disk *disk_car, dword hd_offset); static void aff_CHS_from_LBA_buffer(const t_param_disk *disk_car, dword hd_offset); static void aff_CHS_from_LBA_rapport(const t_param_disk *disk_car, dword hd_offset); int get_string(char *str, int len, char *def) { int c; int i = 0; int x, y; int use_def = FALSE; getyx(stdscr, y, x); wclrtoeol(stdscr); str[0] = 0; if (def != NULL) { mvwaddstr(stdscr,y, x, def); wmove(stdscr,y, x); use_def = TRUE; } wrefresh(stdscr); while ((c = wgetch(stdscr)) != '\n' && c != key_CR) { switch (c) { case key_ESC: wmove(stdscr,y, x); wclrtoeol(stdscr); wrefresh(stdscr); return GS_key_ESCAPE; case KEY_DC: case KEY_BACKSPACE: if (i > 0) { str[--i] = 0; mvaddch(y, x+i, ' '); wmove(stdscr,y, x+i); } else if (use_def) { wclrtoeol(stdscr); use_def = FALSE; } break; default: if (i < len && isprint(c)) { mvaddch(y, x+i, c); if (use_def) { wclrtoeol(stdscr); use_def = FALSE; } str[i++] = c; str[i] = 0; } } wrefresh(stdscr); } if (use_def) return GS_DEFAULT; else return i; } int wgetch_nodelay(WINDOW *window) { int res; nodelay(window,TRUE); res=wgetch(window); nodelay(window,FALSE); return res; } /* * Actual function which prints the button bar and highlights the active button * Should not be called directly. Call function menuSelect instead. */ int wmenuUpdate(WINDOW *window, int y, int x, const struct MenuItem *menuItems, const unsigned int itemLength, const char *available, const int menuType, unsigned int current) { unsigned int i, lmargin = x, ymargin = y; const char *mcd; /* Print available buttons */ for( i = 0; menuItems[i].key!=0; i++ ) { char buff[80]; unsigned int lenName; const char *mi; wmove(window, y, x ); wclrtoeol(window); /* Search next available button */ while( menuItems[i].key!=0 && strchr(available, menuItems[i].key)==NULL ) { i++; } if( menuItems[i].key==0 ) break; /* No more menu items */ /* If selected item is not available and we have bypassed it, make current item selected */ if( current < i && menuItems[current].key < 0 ) current = i; /* If current item is selected, highlight it */ if( current == i ) { /*attron( A_REVERSE )*/ wstandout (window); } /* Print item */ mi = menuItems[i].name; lenName = strlen( mi ); if(lenName>=sizeof(buff)) { ecrit_rapport("\nBUG: %s\n",mi); } if(lenName > itemLength) { if( menuType & MENU_BUTTON ) snprintf(buff, sizeof(buff),"[%s]",mi); else snprintf(buff, sizeof(buff),"%s",mi); } else { if( menuType & MENU_BUTTON ) snprintf( buff, sizeof(buff),"[%*s%-*s]", (itemLength - lenName) / 2, "", (itemLength - lenName + 1) / 2 + lenName, mi ); else snprintf( buff, sizeof(buff),"%*s%-*s", (itemLength - lenName) / 2, "", (itemLength - lenName + 1) / 2 + lenName, mi ); } mvwaddstr(window, y, x, buff ); /* Lowlight after selected item */ if( current == i ) { /*attroff( A_REVERSE )*/ wstandend (window); } /* Calculate position for the next item */ if( menuType & MENU_VERT ) { y += 1; if( y >= WARNING_START ) { y = ymargin; x += itemLength + MENU_SPACING; if( menuType & MENU_BUTTON ) x += 2; } } else { x += itemLength + MENU_SPACING; if( menuType & MENU_BUTTON ) x += 2; if( x > COLUMNS - lmargin - 12 ) { x = lmargin; y ++ ; } } } /* Print the description of selected item */ mcd = menuItems[current].desc; mvwaddstr(window, WARNING_START + 1, (COLUMNS - strlen( mcd )) / 2, mcd ); return y; } /* This function takes a list of menu items, lets the user choose one * * and returns the value keyboard shortcut of the selected menu item */ int wmenuSelect(WINDOW *window, int y, int x, struct MenuItem *menuItems, const unsigned int itemLength, const char *available, int menuType, unsigned int menuDefault) { int i, ylast = y, key = 0; unsigned int current = menuDefault; if( ( menuType & ( MENU_HORIZ | MENU_VERT ) )==0 ) { wdoprintf(window,"Menu without direction. Defaulting horizontal."); menuType |= MENU_HORIZ; } /* Make sure that the current is one of the available items */ while(strchr(available, menuItems[current].key)==NULL) { current ++ ; if( menuItems[current].key==0 ) { current = 0; } } /* Repeat until allowable choice has been made */ while( key==0 ) { /* Display the menu */ ylast = wmenuUpdate( window, y, x, menuItems, itemLength, available, menuType, current ); wrefresh(window); /* Don't put wgetch after the following wclrtoeol */ key = wgetch(window); /* Clear out all prompts and such */ for( i = y; i < ylast; i ++ ) { wmove(window, i, x ); wclrtoeol(window); } wmove(window, WARNING_START + 1, 0 ); wclrtoeol(window); /* Cursor keys */ switch(key) { case KEY_UP: if( menuType & MENU_VERT ) { do { if( current-- == 0 ) { while( menuItems[current+1].key ) current ++ ; } } while( strchr( available, menuItems[current].key )==NULL ); key = 0; } else key = MENU_UP; break; case KEY_DOWN: if( (menuType & MENU_VERT)!=0 ) { do { current ++ ; if( menuItems[current].key==0 ) current = 0 ; } while( strchr( available, menuItems[current].key )==NULL ); key = 0; } else key = MENU_DOWN; break; case KEY_RIGHT: if( menuType & MENU_HORIZ ) { do { current ++ ; if( menuItems[current].key==0 ) { current = 0 ; } } while( strchr( available, menuItems[current].key )==NULL ); key = 0; } else key = MENU_RIGHT; break; case KEY_LEFT: if( menuType & MENU_HORIZ ) { do { if( current-- == 0 ) { while( menuItems[current + 1].key ) current ++ ; } } while( strchr( available, menuItems[current].key )==NULL ); key = 0; } else key = MENU_LEFT; break; } /* Enter equals to the keyboard shortcut of current menu item */ if((key==13) || (key==10) || (key==KEY_ENTER) ||(((menuType & MENU_HORIZ) == 0) && (key==MENU_RIGHT || key==MENU_LEFT))) key = menuItems[current].key; #ifdef PADENTER if(key==PADENTER) key = menuItems[current].key; #endif /* Should all keys to be accepted? */ if( key && (menuType & MENU_ACCEPT_OTHERS) ) break; /* Is pressed key among acceptable ones */ if( key!=0 && (strchr(available, toupper(key))!=NULL || strchr(available, key)!=NULL)) break; /* The key has not been accepted so far -> let's reject it */ #ifdef DEBUG if( key ) { wmove(window,5,0); wdoprintf(window,"key %03X",key); putchar( BELL ); } #endif key = 0; } /* Clear out prompts and such */ for( i = y; i <= ylast; i ++ ) { wmove(window, i, x ); wclrtoeol(window); } wmove(window, WARNING_START + 1, 0 ); wclrtoeol(window); return key; } /* Function menuSelect takes way too many parameters * * Luckily, most of time we can do with this function */ int wmenuSimple(WINDOW *window,struct MenuItem *menuItems, int menuDefault) { unsigned int i, j, itemLength = 0; char available[MENU_MAX_ITEMS]; for(i = 0; menuItems[i].key; i++) { j = strlen(menuItems[i].name); if( j > itemLength ) itemLength = j; available[i] = menuItems[i].key; } available[i] = 0; return wmenuSelect(window,18, 0, menuItems, itemLength, available, MENU_HORIZ | MENU_BUTTON, menuDefault); } /* End of command menu support code */ unsigned int ask_number(const unsigned int val_cur, const unsigned int val_min, const unsigned int val_max, const char * _format, ...) { char res[200]; char res2[200]; char response[LINE_LENGTH]; char def[LINE_LENGTH]; unsigned int tmp_val; va_list ap; va_start(ap,_format); vsnprintf(res,sizeof(res),_format,ap); snprintf(res2,sizeof(res2),"(%u-%u) :",val_min,val_max); va_end(ap); mvwaddstr(stdscr,COMMAND_LINE_Y, COMMAND_LINE_X, res); waddstr(stdscr,res2); sprintf(def, "%u", val_cur); if (get_string(response, LINE_LENGTH, def) > 0) { tmp_val = atoi(response); if (tmp_val >= val_min && tmp_val <= val_max) return tmp_val; } return val_cur; } void aff_copy_full(WINDOW *window) { wclear(window); keypad(window, TRUE); /* Need it to get arrow key */ mvwaddstr(window,0,0,msg_Copyright); #ifdef DJGPP wdoprintf(window,"Dos version\n\n"); #elif defined(BSD) wdoprintf(window,"BSD version\n\n"); #elif defined(LINUX) wdoprintf(window,"Linux version\n\n"); #else wdoprintf(window,"Undefined OS\n\n"); #endif } void aff_copy(WINDOW *window) { wclear(window); keypad(window, TRUE); /* Need it to get arrow key */ mvwaddstr(window,0,0,msg_Copyright); } void dump(WINDOW *window, const void *nom_dump,unsigned int lng) { unsigned int i,j; unsigned int pos=0; unsigned char car; int done=0; int menu=2; /* default : quit */ unsigned int nbr_line; struct MenuItem menuDump[]= { { 'P', "Previous",""}, { 'N', "Next","" }, { 'Q',"Quit","Quit dump section"}, { 0, NULL, NULL } }; nbr_line=lng/0x10; if(lng%0x10!=0) nbr_line++; /* write dump to log file*/ for (i=0; (i<nbr_line); i++) { ecrit_rapport("%04X ",i*0x10); for(j=0; j< 0x10;j++) { if(i*0x10+j<lng) { car=*((const unsigned char *)nom_dump+i*0x10+j); ecrit_rapport("%02x", car); } else ecrit_rapport(" "); if(j%4==(4-1)) ecrit_rapport(" "); } ecrit_rapport(" "); for(j=0; j< 0x10;j++) { if(i*0x10+j<lng) { car=*((const unsigned char*)nom_dump+i*0x10+j); if ((car<32)||(car >= 127)) ecrit_rapport("."); else ecrit_rapport("%c", car); } else ecrit_rapport(" "); } ecrit_rapport("\n"); } /* ncurses interface */ mvwaddstr(window,DUMP_Y,DUMP_X,msg_DUMP_HEXA); /* On pourrait utiliser wscrl */ do { for (i=pos; (i<nbr_line)&&((i-pos)<DUMP_MAX_LINES); i++) { wmove(window,DUMP_Y+i-pos,DUMP_X); wclrtoeol(window); wdoprintf(window,"%04X ",i*0x10); for(j=0; j< 0x10;j++) { if(i*0x10+j<lng) { car=*((const unsigned char*)nom_dump+i*0x10+j); wdoprintf(window,"%02x", car); } else wdoprintf(window," "); if(j%4==(4-1)) wdoprintf(window," "); } wdoprintf(window," "); for(j=0; j< 0x10;j++) { if(i*0x10+j<lng) { car=*((const unsigned char*)nom_dump+i*0x10+j); if ((car<32)||(car >= 127)) wdoprintf(window,"."); else wdoprintf(window,"%c", car); } else wdoprintf(window," "); } } switch (wmenuSelect(window,INTER_DUMP_Y, INTER_DUMP_X, menuDump, 8, "PNQ", MENU_HORIZ | MENU_BUTTON | MENU_ACCEPT_OTHERS, menu)) { case 'p': case 'P': case MENU_UP: menu=0; if(pos>0) pos--; break; case 'n': case 'N': case MENU_DOWN: menu=1; if(pos<nbr_line-DUMP_MAX_LINES) pos++; break; case KEY_PPAGE: menu=0; if(pos>DUMP_MAX_LINES-1) pos-=DUMP_MAX_LINES-1; else pos=0; break; case KEY_NPAGE: menu=1; if(pos<nbr_line-DUMP_MAX_LINES-(DUMP_MAX_LINES-1)) pos+=DUMP_MAX_LINES-1; else pos=nbr_line-DUMP_MAX_LINES; break; case key_ESC: case 'q': case 'Q': done = TRUE; break; } } while(done==FALSE); } void dump2(WINDOW *window, const void *dump_1, const void *dump_2, const unsigned int lng) { unsigned int i,j; unsigned int pos=0; int done=0; int menu=2; /* default : quit */ unsigned int nbr_line; struct MenuItem menuDump[]= { { 'P', "Previous",""}, { 'N', "Next","" }, { 'Q',"Quit","Quit dump section"}, { 0, NULL, NULL } }; nbr_line=lng/0x08; if(nbr_line%0x08) nbr_line++; /* write dump to log file*/ for (i=0; (i<nbr_line); i++) { ecrit_rapport("%04X ",i*0x08); for(j=0; j<0x08;j++) { if(i*0x08+j<lng) { unsigned char car=*((const unsigned char *)dump_1+i*0x08+j); ecrit_rapport("%02x", car); } else ecrit_rapport(" "); if(j%4==(4-1)) ecrit_rapport(" "); } ecrit_rapport(" "); for(j=0; j<0x08;j++) { if(i*0x08+j<lng) { unsigned char car=*((const unsigned char*)dump_1+i*0x08+j); if ((car<32)||(car >= 127)) ecrit_rapport("."); else ecrit_rapport("%c", car); } else ecrit_rapport(" "); } ecrit_rapport(" "); for(j=0; j<0x08;j++) { if(i*0x08+j<lng) { unsigned char car=*((const unsigned char *)dump_2+i*0x08+j); ecrit_rapport("%02x", car); } else ecrit_rapport(" "); if(j%4==(4-1)) ecrit_rapport(" "); } ecrit_rapport(" "); for(j=0; j<0x08;j++) { if(i*0x08+j<lng) { unsigned char car=*((const unsigned char*)dump_2+i*0x08+j); if ((car<32)||(car >= 127)) ecrit_rapport("."); else ecrit_rapport("%c", car); } else ecrit_rapport(" "); } ecrit_rapport("\n"); } /* ncurses interface */ do { for (i=pos; (i<nbr_line)&&((i-pos)<DUMP_MAX_LINES); i++) { wmove(window,DUMP_Y+i-pos,DUMP_X); wclrtoeol(window); wdoprintf(window,"%04X ",i*0x08); for(j=0; j<0x08;j++) { if(i*0x08+j<lng) { unsigned char car=*((const unsigned char*)dump_1+i*0x08+j); wdoprintf(window,"%02x", car); } else wdoprintf(window," "); if(j%4==(4-1)) wdoprintf(window," "); } wdoprintf(window," "); for(j=0; j<0x08;j++) { if(i*0x08+j<lng) { unsigned char car=*((const unsigned char*)dump_1+i*0x08+j); if ((car<32)||(car >= 127)) wdoprintf(window,"."); else wdoprintf(window,"%c", car); } else wdoprintf(window," "); } wdoprintf(window," "); for(j=0; j<0x08;j++) { if(i*0x08+j<lng) { unsigned char car=*((const unsigned char*)dump_2+i*0x08+j); wdoprintf(window,"%02x", car); if(j%4==(4-1)) wdoprintf(window," "); } else wdoprintf(window," "); } wdoprintf(window," "); for(j=0; j<0x08;j++) { if(i*0x08+j<lng) { unsigned char car=*((const unsigned char*)dump_2+i*0x08+j); if ((car<32)||(car >= 127)) wdoprintf(window,"."); else wdoprintf(window,"%c", car); } else wdoprintf(window," "); } } switch (wmenuSelect(window,INTER_DUMP_Y, INTER_DUMP_X, menuDump, 8, "PNQ", MENU_HORIZ | MENU_BUTTON | MENU_ACCEPT_OTHERS, menu)) { case 'p': case 'P': case MENU_UP: menu=0; if(pos>0) pos--; break; case 'n': case 'N': case MENU_DOWN: menu=1; if(pos<nbr_line-DUMP_MAX_LINES) pos++; break; case KEY_PPAGE: menu=0; if(pos>DUMP_MAX_LINES-1) pos-=DUMP_MAX_LINES-1; else pos=0; break; case KEY_NPAGE: menu=1; if(pos<nbr_line-DUMP_MAX_LINES-(DUMP_MAX_LINES-1)) pos+=DUMP_MAX_LINES-1; else pos=nbr_line-DUMP_MAX_LINES; break; case key_ESC: case 'q': case 'Q': done = TRUE; break; } } while(done==FALSE); } int aff_buffer(const buffer_cmd_t cmd, const char *_format, ...) { static char buffer[MAX_LINES][LINE_LENGTH+1]; static int nbr_lines=0; va_list ap; va_start(ap,_format); switch(cmd) { case BUFFER_RESET: { int i; nbr_lines=0; for(i=0;i<MAX_LINES;i++) memset(buffer[i],0,LINE_LENGTH+1); } break; case BUFFER_ADD: { char tmp_line[BUFFER_LINE_LENGTH+1]; char *pos_in_tmp_line=tmp_line-1; memset(tmp_line,'\0',sizeof(tmp_line)); vsnprintf(tmp_line,BUFFER_LINE_LENGTH,_format,ap); while(pos_in_tmp_line!=NULL && (nbr_lines<MAX_LINES)) { char *ret_ligne= strchr(++pos_in_tmp_line,'\n'); if(ret_ligne!=NULL) { strncat(buffer[nbr_lines],pos_in_tmp_line, ret_ligne-pos_in_tmp_line<LINE_LENGTH-strlen(buffer[nbr_lines])?ret_ligne-pos_in_tmp_line:LINE_LENGTH-strlen(buffer[nbr_lines])); if(strlen(buffer[nbr_lines])>0) nbr_lines++; } else { strncat(buffer[nbr_lines],pos_in_tmp_line,LINE_LENGTH-strlen(buffer[nbr_lines])); } pos_in_tmp_line=ret_ligne; } /* ecrit_rapport("aff_buffer %d =>%s<=\n",nbr_lines,tmp_line); */ if(nbr_lines>=MAX_LINES) { ecrit_rapport("aff_buffer too much lines =>%s<=\n",tmp_line); } } break; case BUFFER_DISPLAY: { int i; int menu; int pos=0; int done=0; WINDOW *window=*(WINDOW**)ap; struct MenuItem menuBuffer[]= { { 'P', "Previous",""}, { 'N', "Next","" }, { 'Q',"Quit","Quit this section"}, { 'S',"Search!","Search deeper, try to find more partitions"}, { 'W', "Write","Write partition structure to disk"}, { 'O', "Org. BS","Copy boot sector over backup sector"}, { 'B', "Backup BS","Copy backup boot sector over boot sector"}, { 'R', "Rebuild BS","Rebuild boot sector"}, { 'D', "Dump","Dump boot sector and backup boot sector"}, { 0, NULL, NULL } }; char options[20]; if(nbr_lines<=DUMP_MAX_LINES) { strncpy(options,"Q",sizeof(options)); menu=0; /* default = quit */ } else { strncpy(options,"PNQ",sizeof(options)); menu=1; /* default = next */ } strncat(options,_format,sizeof(options)-strlen(options)); if(buffer[nbr_lines][0]!='\0') nbr_lines++; /* to log file */ for(i=0;i<nbr_lines;i++) ecrit_rapport("%s\n",buffer[i]); /* curses interface */ do { for (i=pos; (i<nbr_lines)&&((i-pos)<DUMP_MAX_LINES); i++) { wmove(window,DUMP_Y+i-pos,DUMP_X); wclrtoeol(window); wdoprintf(window,"%s",buffer[i]); } switch (wmenuSelect(window,INTER_DUMP_Y, INTER_DUMP_X, menuBuffer, 8, options, MENU_HORIZ | MENU_BUTTON | MENU_ACCEPT_OTHERS, menu)) { case 'p': case 'P': case MENU_UP: menu=0; if(pos>0) pos--; break; case 'n': case 'N': case MENU_DOWN: menu=1; if(pos<nbr_lines-DUMP_MAX_LINES) pos++; break; case KEY_PPAGE: menu=0; if(pos>DUMP_MAX_LINES-1) pos-=DUMP_MAX_LINES-1; else pos=0; break; case KEY_NPAGE: menu=1; if(pos<nbr_lines-DUMP_MAX_LINES-(DUMP_MAX_LINES)-1) pos+=DUMP_MAX_LINES-1; else pos=nbr_lines-DUMP_MAX_LINES>0?nbr_lines-DUMP_MAX_LINES:0; break; case 's': case 'S': if(strchr(options,'S')!=NULL) { va_end(ap); return 2; } break; case 'o': case 'O': if(strchr(options,'O')!=NULL) { va_end(ap); return 1; } break; case 'b': case 'B': if(strchr(options,'B')!=NULL) { va_end(ap); return 2; } break; case 'r': case 'R': if(strchr(options,'R')!=NULL) { va_end(ap); return 3; } break; case 'd': case 'D': if(strchr(options,'D')!=NULL) { va_end(ap); return 4; } break; case 'w': case 'W': if(strchr(options,'W')!=NULL) { va_end(ap); return 1; } break; case key_ESC: case 'q': case 'Q': done = TRUE; break; } } while(done!=TRUE); } break; case BUFFER_SHOW: { int i; int pos=nbr_lines-DUMP_MAX_LINES<0?0:nbr_lines-DUMP_MAX_LINES; if(buffer[nbr_lines][0]!='\0') nbr_lines++; /* curses interface */ for (i=pos; (i<nbr_lines)&&((i-pos)<DUMP_MAX_LINES); i++) { wmove(stdscr,DUMP_Y+1+i-pos,DUMP_X); wclrtoeol(stdscr); wdoprintf(stdscr,"%s",buffer[i]); } wrefresh(stdscr); } break; case BUFFER_WRITE: { int i; if(buffer[nbr_lines][0]!='\0') nbr_lines++; /* to log file */ for(i=0;i<nbr_lines;i++) { printf("%s\n",buffer[i]); ecrit_rapport("%s\n",buffer[i]); } } break; } va_end(ap); return 0; } /* part_num 2 PLEX 1 part_type ... CHS 5+1+3+1+2=12 size 9 part_name EXT2 16, FAT 11 part_num PLEX part_type CHS CHS size [part_name] 2 1 1 1 x 1 121 121 9 11 16 1 2+1+1+1+x+1+12+1+12+1+9+1+1+16+1=60+x * */ void aff_part_buffer(const aff_part_type_t newline,const t_param_disk *disk_car,const t_diskext *partition) { switch(newline) { case AFF_PART_NL: aff_buffer(BUFFER_ADD,"\n "); break; case AFF_PART_ORDER: if((partition->status!=STATUS_EXT_IN_EXT) && partition->order!=0) aff_buffer(BUFFER_ADD,"%2d ", partition->order); else aff_buffer(BUFFER_ADD," "); break; case AFF_PART_NONL: case AFF_PART_SHORT: break; } if(newline!=AFF_PART_SHORT) { switch(partition->status) { case STATUS_PRIM: aff_buffer(BUFFER_ADD,"P"); break; case STATUS_PRIM_BOOT: aff_buffer(BUFFER_ADD,"*"); break; case STATUS_EXT: aff_buffer(BUFFER_ADD,"E"); break; case STATUS_EXT_IN_EXT: aff_buffer(BUFFER_ADD,"X"); break; case STATUS_LOG: aff_buffer(BUFFER_ADD,"L"); break; case STATUS_DELETED: aff_buffer(BUFFER_ADD,"D"); break; } } if(nom_os[partition->part_type]!=NULL) aff_buffer(BUFFER_ADD," %-20s ",nom_os[partition->part_type]); else aff_buffer(BUFFER_ADD," Sys=%02X\t\t\t ", partition->part_type); aff_CHS_from_LBA_buffer(disk_car,partition->lba); aff_CHS_from_LBA_buffer(disk_car,partition->lba+partition->part_size-1); aff_buffer(BUFFER_ADD,"%10lu", partition->part_size); if(partition->name[0]!='\0') aff_buffer(BUFFER_ADD," [%s]",partition->name); if(newline==AFF_PART_ORDER || newline==AFF_PART_SHORT) aff_buffer(BUFFER_ADD,"\n"); } void aff_entry(const struct partition_dos *entree) { if(nom_os[entree->sys_ind]!=NULL) wdoprintf(stdscr,"\n %-20s ",nom_os[entree->sys_ind]); else wdoprintf(stdscr,"\n Sys=%02X\t\t\t ", entree->sys_ind); wdoprintf(stdscr,"%4u %3u %2u" " %4u %3u %2u" " %10u" " %10u", s_cyl(entree),s_head(entree),s_sect(entree), e_cyl(entree),e_head(entree),e_sect(entree), get_start_sect(entree),get_nr_sects(entree)); } void aff_entry_rapport(const struct partition_dos *entree) { if(nom_os[entree->sys_ind]!=NULL) ecrit_rapport(" %-20s ",nom_os[entree->sys_ind]); else ecrit_rapport(" Sys=%02X\t\t\t ", entree->sys_ind); ecrit_rapport("%4u %3u %2u" " %4u %3u %2u" " %10u" " %10u\n", s_cyl(entree),s_head(entree),s_sect(entree), e_cyl(entree),e_head(entree),e_sect(entree), get_start_sect(entree),get_nr_sects(entree)); } void aff_CHS_rapport(const t_CHS * CHS) { ecrit_rapport("%5u %3u %2u ", CHS->cylinder, CHS->head, CHS->sector); } void aff_CHS(const t_CHS * CHS) { wdoprintf(stdscr,"%5u %3u %2u ", CHS->cylinder, CHS->head, CHS->sector); } void aff_CHS_buffer(const t_CHS * CHS) { aff_buffer(BUFFER_ADD,"%5u %3u %2u ", CHS->cylinder, CHS->head, CHS->sector); } static void aff_CHS_from_LBA(WINDOW *window, const t_param_disk *disk_car, dword hd_offset) { wdoprintf(window,"%5u %3u %2u ", LBA2cylinder(disk_car,hd_offset), LBA2head(disk_car,hd_offset),LBA2sector(disk_car,hd_offset)); } static void aff_CHS_from_LBA_buffer(const t_param_disk *disk_car, dword hd_offset) { aff_buffer(BUFFER_ADD,"%5u %3u %2u ", LBA2cylinder(disk_car,hd_offset), LBA2head(disk_car,hd_offset),LBA2sector(disk_car,hd_offset)); } static void aff_CHS_from_LBA_rapport(const t_param_disk *disk_car, dword hd_offset) { ecrit_rapport("%5u %3u %2u ", LBA2cylinder(disk_car,hd_offset), LBA2head(disk_car,hd_offset),LBA2sector(disk_car,hd_offset)); } void aff_part_rapport(const t_param_disk *disk_car,const t_diskext *partition) { if((partition->status!=STATUS_EXT_IN_EXT) && (partition->order!=0)) ecrit_rapport("%2d ", partition->order); else ecrit_rapport(" "); switch(partition->status) { case STATUS_PRIM: ecrit_rapport("P"); break; case STATUS_PRIM_BOOT: ecrit_rapport("*"); break; case STATUS_EXT: ecrit_rapport("E"); break; case STATUS_EXT_IN_EXT: ecrit_rapport("X"); break; case STATUS_LOG: ecrit_rapport("L"); break; case STATUS_DELETED: ecrit_rapport("D"); break; } if(nom_os[partition->part_type]!=NULL) ecrit_rapport(" %-20s ",nom_os[partition->part_type]); else ecrit_rapport(" Sys=%02X\t\t\t ", partition->part_type); aff_CHS_from_LBA_rapport(disk_car,partition->lba); aff_CHS_from_LBA_rapport(disk_car,partition->lba+partition->part_size-1); ecrit_rapport("%10lu", partition->part_size); if(partition->name[0]!='\0') ecrit_rapport(" [%s]",partition->name); if(partition->info[0]!='\0') ecrit_rapport("\n %s",partition->info); ecrit_rapport("\n"); } void aff_part(WINDOW *window,const aff_part_type_t newline,const t_param_disk *disk_car,const t_diskext *partition) { switch(newline) { case AFF_PART_NL: wdoprintf(window,"\n "); break; case AFF_PART_ORDER: if(partition->status!=STATUS_EXT_IN_EXT) wdoprintf(window,"%2d ", partition->order); else wdoprintf(window," "); break; case AFF_PART_NONL: case AFF_PART_SHORT: break; } if(newline!=AFF_PART_SHORT) { switch(partition->status) { case STATUS_PRIM: wdoprintf(window,"P"); break; case STATUS_PRIM_BOOT: wdoprintf(window,"*"); break; case STATUS_EXT: wdoprintf(window,"E"); break; case STATUS_EXT_IN_EXT: wdoprintf(window,"X"); break; case STATUS_LOG: wdoprintf(window,"L"); break; case STATUS_DELETED: wdoprintf(window,"D"); break; } } if(nom_os[partition->part_type]!=NULL) wdoprintf(window," %-20s ",nom_os[partition->part_type]); else wdoprintf(window," Sys=%02X\t\t\t ", partition->part_type); aff_CHS_from_LBA(window,disk_car,partition->lba); aff_CHS_from_LBA(window,disk_car,partition->lba+partition->part_size-1); wdoprintf(window,"%10lu", partition->part_size); if(partition->name[0]!='\0') wdoprintf(window," [%s]",partition->name); } void aff_LBA2CHS(const t_param_disk *disk_car, const dword pos_LBA) { dword tmp; dword cylinder, head, sector; tmp=disk_car->CHS.sector; sector=(pos_LBA%tmp)+1; tmp=pos_LBA/tmp; cylinder=tmp/(disk_car->CHS.head+1); head=tmp%(disk_car->CHS.head+1); wdoprintf(stdscr,"%lu/%lu/%lu", cylinder,head,sector); } void aff_LBA2CHS_rapport(const t_param_disk *disk_car, const dword pos_LBA) { dword tmp; dword cylinder, head, sector; tmp=disk_car->CHS.sector; sector=(pos_LBA%tmp)+1; tmp=pos_LBA/tmp; cylinder=tmp/(disk_car->CHS.head+1); head=tmp%(disk_car->CHS.head+1); ecrit_rapport("%lu/%lu/%lu", cylinder,head,sector); } void interface_list(t_param_disk *disk_car, const int debug,const int test_recovery) { /* log */ t_list_part *list_part; ecrit_rapport("\nAnalyse "); ecrit_rapport("%s",disk_car->description(disk_car)); printf("%s",disk_car->description(disk_car)); list_part=read_part(disk_car, debug); aff_buffer(BUFFER_WRITE,"Q"); if(test_recovery) { t_list_part *element; ecrit_rapport("rebuild_FAT_BS()\n"); for(element=list_part;element!=NULL;element=element->next) { if(is_fat(element->part->part_type)) /* do not use upart_type */ { aff_part_rapport(disk_car,element->part); rebuild_FAT_BS(disk_car,element->part,debug,0,0); /* dump_ind */ } } } delete_list_part(list_part); } int ask_YN(WINDOW *window,const char* msg) { char res; wdoprintf(window,"%s",msg); wrefresh(window); do { res=toupper(wgetch(window)); } while((res!=c_NO)&(res!=c_YES)); wdoprintf(window,"%c\n",res); return (res==c_YES); } int ask_confirmation(const char*msg) { int res; WINDOW *window=newwin(0,0,0,0); /* full screen */ aff_copy(window); res=ask_YN(window,msg); delwin(window); #ifdef DJGPP wredrawln(stdscr,0,stdscr->_maxy); /* redrawwin def is boggus in pdcur24 */ #else redrawwin(stdscr); /* stdscr has been corrupted by window */ #endif return res; } int wdoprintf(WINDOW *window, const char *_format, ...) { char res[800]; va_list ap; va_start(ap,_format); vsnprintf(res,sizeof(res),_format,ap); va_end(ap); return waddstr(window,res); } int display_message(const char*msg) { int pipo=0; static struct MenuItem menuGeometry[]= { { 'O', "Ok", "" }, { 0, NULL, NULL } }; WINDOW *window=newwin(0,0,0,0); /* full screen */ aff_copy(window); mvwaddstr(window,5,0,msg); wmenuSimple(window,menuGeometry, pipo); delwin(window); #ifdef DJGPP wredrawln(stdscr,0,stdscr->_maxy); /* redrawwin def is boggus in pdcur24 */ #else redrawwin(stdscr); /* stdscr has been corrupted by window */ #endif ecrit_rapport("%s",msg); return 0; } int write_MBR_code(t_param_disk *disk_car) { if(ask_YN(stdscr,msg_WRITE_MBR_CODE)!=0 && ask_confirmation("Write a new copy of MBR code, confirm ? (Y/N)")!=0) { unsigned char buffer[SECTOR_SIZE]; if(read_MBR(disk_car,&buffer)!=0) return 1; write_MBR_code_aux(buffer); return write_MBR(disk_car,&buffer); } return 0; } int write_clean_table(t_param_disk *disk_car) { unsigned char buffer[SECTOR_SIZE]; if(ask_YN(stdscr,msg_WRITE_CLEAN_TABLE)!=0 && ask_confirmation("Clear partition table, confirm ? (Y/N)")!=0) { if(read_MBR(disk_car,&buffer)!=0) return 1; memset(&buffer[TAB_PART],0,0x40); return write_MBR(disk_car,&buffer); } return 0; } int do_curses_testdisk(int debug,int paranoid,int dump_ind, int fast_mode,int align,int do_analyse, const t_list_disk *list_disk) { int command; int done=0; int recover_cih=0; int allow_partial_last_cylinder=0; int ask_part_order=0; int halt_on_errors=1; int max_ext=0; const t_list_disk *element_disk; const t_list_disk *current_disk=list_disk; static struct MenuItem menuMain[]= { {'A',"Analyse","Analyse current partition structure and search for lost partitions"}, {'D',"Delete","Delete all data in the partition table"}, {'C',"MBR Code","Write the Classic MBR code to first sector"}, {'G',"Geometry", "Change disk geometry (expert only)" }, {'O',"Options","Modify options"}, {'E',"Editor","Basic disk editor"}, {'T',"Advanced","Advanced boot recovery"}, {'Q',"Quit","Quit program"}, {0,NULL,NULL} }; if(list_disk==NULL) return 0; /* use_env(TRUE); */ initscr(); noecho(); keypad(stdscr, TRUE); /* Need it to get arrow key */ #ifndef DJGPP nonl(); /*don't use for Dos version but enter will work with it... dilema */ #endif crmode(); /* intrflush(stdscr, FALSE); */ cbreak(); if(LINES<25) { ecrit_rapport("Terminal has only %u lines\n",LINES); nl(); endwin(); return 1; } /* ncurses interface */ while(done==0) { aff_copy_full(stdscr); wmove(stdscr,5,0); for(element_disk=list_disk;element_disk!=NULL;element_disk=element_disk->next) { if(element_disk!=current_disk) wdoprintf(stdscr,"%s",element_disk->disk->description(element_disk->disk)); else { wstandout(stdscr); wdoprintf(stdscr,"%s",element_disk->disk->description(element_disk->disk)); wstandend(stdscr); } } current_disk->disk->halt_on_errors=halt_on_errors; command = toupper(wmenuSelect(stdscr,INTER_MAIN_Y, INTER_MAIN_X, menuMain, 8, "AGDCOTQ", MENU_HORIZ | MENU_BUTTON | MENU_ACCEPT_OTHERS, 0)); /* e for editor will be added when the editor will be better */ switch(command) { case 'G': change_geometry(current_disk->disk); break; case 'D': wmove(stdscr,INTER_MAIN_Y,INTER_MAIN_X); write_clean_table(current_disk->disk); break; case 'C': wmove(stdscr,INTER_MAIN_Y,INTER_MAIN_X); write_MBR_code(current_disk->disk); break; case 'A': if(do_analyse) interface_analyse(current_disk->disk,debug); interface_recovery(current_disk->disk,paranoid,debug, dump_ind, fast_mode,align,recover_cih,ask_part_order,max_ext); break; case 'T': /* Test */ interface_adv(current_disk->disk, debug, dump_ind); break; case 'E': interface_editor(current_disk->disk); break; case 'Q': done = 1; break; case 'O': { int old_allow_partial_last_cylinder=allow_partial_last_cylinder; interface_options(¶noid,&dump_ind,&fast_mode,&align,&recover_cih,&allow_partial_last_cylinder,&ask_part_order,&halt_on_errors,&max_ext); if(old_allow_partial_last_cylinder!=allow_partial_last_cylinder) hd_parse_bis(list_disk,allow_partial_last_cylinder); } break; case MENU_UP: if(current_disk->prev!=NULL) current_disk=current_disk->prev; break; case MENU_DOWN: if(current_disk->next!=NULL) current_disk=current_disk->next; break; #ifdef DEBUG default: wmove(stdscr,10,0); wdoprintf(stdscr,"key %03X %d", command, command); wrefresh(stdscr); break; #endif } } wclear(stdscr); wrefresh(stdscr); nl(); endwin(); ecrit_rapport("\n"); return 0; } void interface_analyse(t_param_disk *disk_car, const int debug) { /* log */ ecrit_rapport("\nAnalyse "); ecrit_rapport("%s",disk_car->description(disk_car)); /* ncurses interface */ aff_copy(stdscr); mvwaddstr(stdscr,23,0,msg_PART_TYPE); wmove(stdscr,4,0); wdoprintf(stdscr,"%s",disk_car->description(disk_car)); mvwaddstr(stdscr,5,0,"Check current partition structure"); wmove(stdscr,6,0); wrefresh(stdscr); delete_list_part(read_part(disk_car, debug)); ecrit_rapport("Current partitions:\n"); aff_buffer(BUFFER_DISPLAY,"Q",stdscr); } int interface_write(t_param_disk *disk_car,t_list_part *list_part,const int can_search_deeper) { t_list_part *parts; ecrit_rapport("\ninterface_write()\n"); aff_copy(stdscr); wmove(stdscr,4,0); wdoprintf(stdscr,"%s",disk_car->description(disk_car)); wmove(stdscr,5,0); aff_buffer(BUFFER_RESET,"Q"); mvwaddstr(stdscr,6,0,msg_PART_HEADER_WRITE); for(parts=list_part;parts!=NULL;parts=parts->next) if(parts->part->status!=STATUS_LOG) aff_part_buffer(AFF_PART_ORDER,disk_car,parts->part); for(parts=list_part;parts!=NULL;parts=parts->next) if(parts->part->status==STATUS_LOG) aff_part_buffer(AFF_PART_ORDER,disk_car,parts->part); return aff_buffer(BUFFER_DISPLAY,can_search_deeper?"SW":"W",stdscr); } static void interface_options(int *paranoid,int *dump_ind,int *fast_mode,int *align,int *recover_cih, int *allow_partial_last_cylinder,int *ask_part_order,int *halt_on_errors, int *max_ext) { /* paranoid: search in partition * dump_ind dump sector Y/N * fast_mode Partitions are aligned on cylinder boundary Y/N * */ int done = FALSE; int menu = 9; /* ncurses interface */ while (done==FALSE) { int car; struct MenuItem menuOptions[]= { { 'P', NULL, "Search all partitions" }, { 'D',NULL,"Dump essential sectors" }, { 'C',NULL,"Partitions are aligned on cylinder boundary" }, { 'F',NULL,"Don't check every hard disk head" }, { 'T',NULL,"WARNING: ONLY WORKS WITH FAT PARTITION TYPES" }, { 'A',NULL,""}, { 'O',NULL,""}, { 'E',NULL,"Halt on Disk I/O errors" }, { 'M',NULL,""}, { 'Q',"Quit","Return to main menu"}, { 0, NULL, NULL } }; menuOptions[0].name=*paranoid?"Paranoid : Yes":"Paranoid : No"; menuOptions[1].name=*dump_ind?"Dump : Yes":"Dump : No"; menuOptions[2].name=*align?"Cylinder boundary : Yes":"Cylinder boundary : No"; switch(*fast_mode) { case 0: menuOptions[3].name="Mode : Fast"; break; case 1: menuOptions[3].name="Mode : Medium"; break; default: menuOptions[3].name="Mode : Slow"; break; } menuOptions[4].name=*recover_cih?"Recover from CIH virus : Yes":"Recover from CIH virus : No"; menuOptions[5].name=*allow_partial_last_cylinder?"Allow partial last cylinder : Yes":"Allow partial last cylinder : No"; menuOptions[6].name=*ask_part_order?"Ask partition order : Yes":"Ask partition order : No"; menuOptions[7].name=*halt_on_errors?"Halt on errors : Yes":"Halt on errors : No"; menuOptions[8].name=*max_ext?"Maximize extended part : Yes":"Maximize extended part : No"; /* car=toupper( wmenuSelect(stdscr,INTER_OPTION_Y, INTER_OPTION_X, menuOptions, 0, "PDCFAOEMQ", MENU_VERT, menu)); */ car=toupper( wmenuSelect(stdscr,INTER_OPTION_Y, INTER_OPTION_X, menuOptions, 0, "DCAOEMQ", MENU_VERT, menu)); switch(car) { case 'P': *paranoid=!*paranoid; menu=0; break; case 'D': *dump_ind=!*dump_ind; menu=1; break; case 'C': *align=!*align; menu=2; break; case 'F': if(*fast_mode<2) (*fast_mode)++; else *fast_mode=0; menu=3; break; case 'T': *recover_cih=!*recover_cih; menu=4; break; case 'A': *allow_partial_last_cylinder=!*allow_partial_last_cylinder; menu=5; break; case 'O': *ask_part_order=!*ask_part_order; menu=6; break; case 'E': *halt_on_errors=!*halt_on_errors; menu=7; break; case 'M': *max_ext=!*max_ext; menu=8; break; case key_ESC: case 'Q': done = TRUE; break; } } /* write new options to log file */ ecrit_rapport("New options :\n Paranoid : %s\n Dump : %s\n Cylinder boudary : %s\n fast_mode=%d(0=fast)\n Allow partial last cylinder : %s\n Ask partition order : %s\n Halt on errors : %s\n Recover from CIH virus : %s\n Maximize extended part : %s\n", *paranoid?"Yes":"No", *dump_ind?"Yes":"No", *align?"Yes":"No", *fast_mode, *allow_partial_last_cylinder?"Yes":"No", *ask_part_order?"Yes":"No", *halt_on_errors?"Yes":"No", *recover_cih?"Yes":"No", *max_ext?"Yes":"No"); } t_list_part *ask_structure(t_param_disk *disk_car,t_list_part *list_part, const int debug) { int quit=0; int offset=0; int pos_num=0; t_list_part *pos=list_part; int rewrite=1; do { int i; t_list_part *parts; int car; if(rewrite) { aff_copy(stdscr); wmove(stdscr,4,0); wdoprintf(stdscr,"%s",disk_car->description(disk_car)); mvwaddstr(stdscr,23,0,msg_PART_TYPE); mvwaddstr(stdscr,5,0,msg_CHOOSE_PART_TYPE); mvwaddstr(stdscr,6,0,msg_CHOOSE_PART_TYPE_END); mvwaddstr(stdscr,7,0,msg_PART_HEADER2); rewrite=0; } for(i=0,parts=list_part;(parts!=NULL) && (i<offset);parts=parts->next,i++); for(i=offset;(parts!=NULL) &&((i-offset)<INTER_STRUCTURE);i++,parts=parts->next) { wmove(stdscr,8+i-offset,0); wclrtoeol(stdscr); /* before addstr for BSD compatibility */ if(parts==pos) { wstandout(stdscr); aff_part(stdscr,AFF_PART_NONL,disk_car,parts->part); wstandend(stdscr); wmove(stdscr,24,0); wclrtoeol(stdscr); /* before addstr for BSD compatibility */ waddstr(stdscr,parts->part->info); } else { aff_part(stdscr,AFF_PART_NONL,disk_car,parts->part); } } if(test_structure(list_part)!=0) mvwaddstr(stdscr,22,0,msg_STRUCT_BAD); else mvwaddstr(stdscr,22,0,msg_STRUCT_OK); wmove(stdscr,22,15); wclrtoeol(stdscr); /* before addstr for BSD compatibility */ waddstr(stdscr,"Keys a: add partition"); if(list_part!=NULL) { waddstr(stdscr,", T: change type"); switch(pos->part->upart_type) { case UP_EXT2: case UP_EXT3: case UP_RFS: case UP_RFS2: case UP_FAT12: case UP_FAT16: case UP_FAT32: case UP_NTFS: waddstr(stdscr,", P: list files"); break; default: break; } } wrefresh(stdscr); car=wgetch(stdscr); switch(car) { case 'q': case '\r': case '\n': case KEY_ENTER: #ifdef PADENTER case PADENTER: #endif case 'M': quit=1; break; } switch(car) { case KEY_UP: if(list_part!=NULL) { only_one_bootable(list_part,pos); if(pos->prev!=NULL) { pos=pos->prev; pos_num--; } if(pos_num<offset) offset--; } break; case KEY_DOWN: if(list_part!=NULL) { only_one_bootable(list_part,pos); if(pos->next!=NULL) { pos=pos->next; pos_num++; } if(pos_num>=offset+INTER_STRUCTURE) offset++; } break; case KEY_PPAGE: if(list_part!=NULL) { only_one_bootable(list_part,pos); for(i=0;(i<INTER_STRUCTURE) && (pos->prev!=NULL);i++) { pos=pos->prev; pos_num--; if(pos_num<offset) offset--; } } break; case KEY_NPAGE: if(list_part!=NULL) { only_one_bootable(list_part,pos); for(i=0;(i<INTER_STRUCTURE) && (pos->next!=NULL);i++) { pos=pos->next; pos_num++; if(pos_num>=offset+INTER_STRUCTURE) offset++; } } break; case KEY_RIGHT: case '+': case ' ': if(list_part!=NULL) { if(pos->part->status==STATUS_LOG) pos->part->status=STATUS_DELETED; else pos->part->status++; if(pos->part->status==STATUS_LOG && can_be_ext(disk_car,pos->part)==0) pos->part->status=STATUS_DELETED; } break; case KEY_LEFT: case '-': if(list_part!=NULL) { if(pos->part->status==STATUS_DELETED) pos->part->status=STATUS_LOG; else pos->part->status--; if(pos->part->status==STATUS_LOG && can_be_ext(disk_car,pos->part)==0) pos->part->status--; } break; case 'a': case 'A': { list_part=add_partition(disk_car,list_part, debug); rewrite=1; offset=0; pos_num=0; pos=list_part; } break; case 't': case 'T': if(list_part!=NULL) { rewrite=1; change_part_type(disk_car,pos->part); } break; case 'p': case 'P': if(list_part!=NULL) { WINDOW *window=newwin(0,0,0,0); /* full screen */ aff_copy(window); switch(pos->part->upart_type) { case UP_FAT12: case UP_FAT16: case UP_FAT32: dir_partition_fat(window,disk_car,pos->part,debug); break; case UP_EXT2: case UP_EXT3: dir_partition_ext2(window,disk_car,pos->part,debug); break; case UP_RFS: case UP_RFS2: dir_partition_reiser(window,disk_car,pos->part,debug); break; case UP_NTFS: dir_partition_ntfs(window,disk_car,pos->part,debug); break; default: break; } delwin(window); #ifdef DJGPP wredrawln(stdscr,0,stdscr->_maxy); /* redrawwin def is boggus in pdcur24 */ #else redrawwin(stdscr); /* stdscr has been corrupted by window */ #endif } break; default: /* ecrit_rapport("ask_structure car=%x\n",car); */ break; } } while(quit==0); return list_part; }